home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 283_01 / lvideo.asm < prev    next >
Assembly Source File  |  1988-12-15  |  33KB  |  782 lines

  1.  
  2. ; LVIDEO.ASM - after Microsoft Systems Journal, Nov. 1988, p. 6
  3. ;
  4. ;               *** Caution: Large Model stack bias! ***
  5. ;
  6. ; This program handles direct writes to the IBM PC video screen buffer
  7. ; located in RAM memory.  Works with all 100% compatible clones, and
  8. ; correctly eliminates snow when using CGA.  See the article in MSJ:
  9. ; "Building a device-independent video display I/O library in Microsoft C",
  10. ; by Jeff Prosise.  Requires MASM v5.0 or MASM v5.1, per documentation.
  11. ;
  12. ; Memory model support by David C. Oshel, Ames, Iowa, Dec. 9, 1988.
  13. ; This file is essentially ASMVIDEO.ASM, modified for appropriate function
  14. ; calls and returns, and DS register management for various data objects.
  15. ;
  16. ; I've added four additional functions, all of which take a len argument,
  17. ; to Prosise's original set of three:
  18. ;                               
  19. ;                  MSJ_SetFldAttr, MSJ_DispMsgLen    12/10/88
  20. ;                  MSJ_MovScrBuf,  MSJ_MovBufScr     12/11/88
  21. ;
  22. ; Added Wozniak's pattern fill to MSJ_SetFldAttr on 12/12/88, and figured
  23. ; out why I still had snow on a CGA (NCR PC 6300) on 12/13/88.  See next.
  24. ;
  25. ;                         *** C A U T I O N ***
  26. ;
  27. ; It turns out that Prosise's XCHG AX,BX and STOSW pattern in the snow
  28. ; elimination code is a VERY time critical optimization.  I actually had
  29. ; to read the article before I could expand on the original routines.  Ouch.
  30. ;       --- 12/13/88, d.c.oshel
  31. ;
  32.  
  33.         .MODEL LARGE
  34.         .CODE
  35.         PUBLIC _MSJ_MovBufScr, _MSJ_MovScrBuf
  36.         PUBLIC _MSJ_SetFldAttr, _MSJ_DispMsgLen
  37.         PUBLIC _MSJ_DispString, _MSJ_DispCharAttr, _MSJ_GetCharAttr
  38.  
  39.  
  40. ;
  41. ; The C interface for these functions and structures looks like this:
  42. ;
  43. ;struct MSJ_VideoInfo {
  44. ;    unsigned char mode;
  45. ;    unsigned char rows;
  46. ;    unsigned char columns;
  47. ;    unsigned char ColorFlag;
  48. ;    unsigned char SnowFlag;
  49. ;    unsigned int  BufferStart;
  50. ;    unsigned int  SegAddr;
  51. ;};
  52. ;
  53. ;extern struct MSJ_VideoInfo video;  /* defined in CVIDEO.C */
  54. ;
  55. ;
  56. ;/* MSJ, Nov. 1988
  57. ;   */
  58. ;extern int cdecl MSJ_GetCharAttr( char row, char col, 
  59. ;                                  struct MSJ_VideoInfo * sptr );
  60. ;
  61. ;/* MSJ, Nov. 1988
  62. ;   */
  63. ;extern void cdecl MSJ_DispCharAttr( char ch, 
  64. ;                                    char row, char col, 
  65. ;                                    char VideoAttr, 
  66. ;                                    struct MSJ_VideoInfo * sptr );
  67. ;
  68. ;
  69. ;/* MSJ, Nov. 1988
  70. ;   */
  71. ;extern void cdecl MSJ_DispString( char * msg, 
  72. ;                                  char row, char col, 
  73. ;                                  char VideoAttr, 
  74. ;                                  struct MSJ_VideoInfo * sptr ); 
  75. ;
  76. ;
  77. ;/* MSJ_DispMsgLen is like MSJ_DispString, but takes a length argument,
  78. ;   and does not disturb screen attributes in the receiving field
  79. ;   12/10/88, d.c.oshel
  80. ;   */
  81. ;extern void cdecl MSJ_DispMsgLen( char * msg, 
  82. ;                                  char row, char col, 
  83. ;                                  int len,
  84. ;                                  struct MSJ_VideoInfo * sptr ); 
  85. ;
  86. ;
  87. ;/* MSJ_SetFldAttr takes a length argument and clears a field of the
  88. ;   screen to the given char having the given attribute
  89. ;   12/10/88, d.c.oshel
  90. ;   */
  91. ;extern void cdecl MSJ_SetFldAttr( char ch, 
  92. ;                                  char row, 
  93. ;                                  char col, 
  94. ;                                  char VideoAttr,
  95. ;                                  int len,
  96. ;                                  struct MSJ_VideoInfo * sptr );
  97. ;
  98. ;
  99. ;/* move count WORDS from screen to far buffer, 12/10/88, d.c.oshel 
  100. ;   */
  101. ;extern void cdecl MSJ_MovScrBuf(  int far * buffer,
  102. ;                                  char row,
  103. ;                                  char col,
  104. ;                                  int count,
  105. ;                                  struct MSJ_VideoInfo * sptr );
  106. ;
  107. ;
  108. ;/* move count WORDS from far buffer to screen, 12/10/88, d.c.oshel 
  109. ;   */
  110. ;extern void cdecl MSJ_MovBufScr(  int far * buffer,
  111. ;                                  char row,
  112. ;                                  char col,
  113. ;                                  int count,
  114. ;                                  struct MSJ_VideoInfo * sptr );
  115. ;
  116.  
  117.  
  118. ;-----------------------------------------------------------------------
  119. ; _MSJ_MovBufScr   copies count words from the user's save buffer to 
  120. ;                  the active video buffer
  121. ;                  12/10/88, d.c.oshel 
  122. ;
  123. ; _MSJ_MovScrBuf   copies count words from the active video buffer to 
  124. ;                  the user's save buffer
  125. ;                  12/10/88, d.c.oshel 
  126. ;-----------------------------------------------------------------------
  127. ;
  128. ; Arguments on the stack (LARGE MODEL):
  129. ;
  130. ;                       [bp+18]  <--- seg\ struct MSJ_VideoInfo far * sptr
  131. ;                       [bp+16]  <--- ofs/ 
  132. ;                       [bp+14]  <--- int count
  133. ;                       [bp+12]  <--- char col
  134. ;                       [bp+10]  <--- char row
  135. ;                       [bp+8]   <--- seg\ int far * buffer
  136. ;                       [bp+6]   <--- ofs/ 
  137. ;
  138. _MSJ_MovBufScr  PROC
  139.                 push    bp      ;save regs & establish stack frame
  140.                 mov     bp,sp
  141.                 push    si
  142.                 push    di
  143.                 push    es
  144.                 push    ds      ;large model uses data segments anywhere
  145.  
  146. ; COUNT:        load CX with the number of bytes to move
  147. ;
  148.                 mov     cx,[bp+14]      ;CX <-- count
  149.                 cmp     cx,1            ;we're already done if CX <= 0
  150.                 jl      exitmbs
  151.  
  152. ; DESTINATION:  set ES:DI to point to screen buffer absolute address
  153. ;               note - this changes DS to video structure's segment
  154. ;
  155.                 lds     bx,[bp+16]          ;DS:BX <-- ptr to video structure
  156.                 test    byte ptr [bx+4], 1  ;is video.SnowFlag clear?
  157.                 pushf                       ;save answer for later
  158.  
  159.                 mov     dh,[bp+10]  ;DH <-- row
  160.                 mov     dl,[bp+12]  ;DL <-- col
  161.                 call    AddressOf   ;DI <-- screen offset
  162.                 mov     es,[bx+8]   ;ES <-- video.SegAddr (screen segment)
  163.                                          
  164. ; SOURCE:       set DS:SI to point to user's save buffer
  165. ;
  166.                 lds     si,[bp+6]       ;DS:SI <-- ptr to source
  167.                 cld
  168.                 popf
  169.                 jnz     hardway
  170.  
  171. ; BEST CASE, move the string from DS:SI to ES:DI, with immediate writes
  172. ;
  173.                 rep     movsw           ;move all immediately
  174.                 jmp     exitmbs
  175.  
  176. hardway:        lodsw                   ;get char from buffer
  177.                 xchg    ax,bx
  178.  
  179.                 cli                     ;disable interrupts
  180.                 mov     dx,3DAh         ;DX <- ptr to Status Register
  181. st1:            in      al,dx           ;if we've arrived during a
  182.                 test    al,1            ;horizontal blanking interval,
  183.                 jnz     st1             ;must wait for the start of next!
  184. st2:            in      al,dx           ;bit one is horizontal retrace
  185.                 test    al,1            ;bit three is vertical retrace
  186.                 jz      st2             ;if nz, horizontal blanking is NOW.
  187.  
  188.                 ; Move up to 16 bits ONLY to the screen, taking advantage
  189.                 ; of the 8088's 4-byte prefetch buffer to save time (!),
  190.                 ; during the 7 microseconds of horizontal blanking;
  191.                 ; Prosise says timing is so tight we MUST use the XCHG
  192.                 ; instruction to get AX back, and nothing else will do.
  193.                 ;
  194.                 ; There are 200 horizontal retrace intervals per frame,
  195.                 ; only one vertical retrace interval per frame; i.e., 200
  196.                 ; lines on the screen, horizontal retrace is the zag
  197.                 ; following raster scan's zig, vertical retrace is the
  198.                 ; corner-to-corner diagonal path back to top of screen.
  199.                 ;
  200.                 ; For reference, 65 clock cycles are about 14 µsec. on
  201.